using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEngine;
using UnityEngine.UIElements;

namespace XLFrame.NodeEditor.window
{
    /// <summary>
    /// 节点窗体类父级,注意请在脚本面板中设置VisualTreeAsset
    /// 负责保存数据等功能
    /// </summary>
    public abstract class NodeWindowBase : EditorWindow
    {
        [SerializeField]
        private VisualTreeAsset m_VisualTreeAsset = default;

        protected Label m_posHint;
        protected Label m_nodeTitle;
        protected NodeGraphViewBase m_nodeView;
        protected NodeTreeFile NodeTreeData;
        protected VisualElement m_propertiesPanel;

        
        protected static Dictionary<int,NodeWindowBase> m_windows = new Dictionary<int, NodeWindowBase>();
        private bool m_isInit = false;

        protected virtual void Init()
        {
            m_isInit = true;
            VisualElement root = rootVisualElement;
            m_posHint = root.Q<Label>("PosHint");
            m_nodeView = root.Q<NodeGraphViewBase>("NodeView");
            m_nodeTitle = root.Q<Label>("NodeTitle");
            m_propertiesPanel = root.Q<VisualElement>("m_propertiesPanel");
            
            m_nodeView.NodeTreeDataBase = NodeTreeData.NodeTreeData;
            m_nodeView.Init();
            
            // 监听键盘事件
            root.RegisterCallback<KeyDownEvent>(OnKeyDownEvent);

            // 也许是unity BUG 不设置无法监听到键盘事件
            m_nodeView.focusable = true;  // 打开按键监听

            m_nodeView.OnMouseMoveEvent += NodeView_OnMouseMove;
            m_nodeView.OnViewScaleEvent += NodeView_OnViewScale;
            m_nodeView.OnDataUpdateEvent += NodeView_OnDataUpdate;

            root.Q<Button>("SaveButton").clicked += SaveButton_Clicked;
        }
        
        public void CreateGUI()
        {
            VisualElement root = rootVisualElement;
            VisualElement labelFromUxml = m_VisualTreeAsset.Instantiate();
            // 设置样式以确保元素填充整个窗口
            labelFromUxml.style.flexGrow = 1; // 这使得元素能够填充其父元素的所有可用空间
            root.Add(labelFromUxml);

            if (m_isInit)
            {
                Init();
            }
           
        }

        [OnOpenAsset(1)]
        public static bool OnOpenAssets(int id, int line)
        {
            // 找到继承自NodeWindowBase所有类
            // 通过反射调用OnOpenAssets
            var nodeWindowBaseType = typeof(NodeWindowBase);
            foreach (var type in nodeWindowBaseType.Assembly.GetTypes())
            {
                if (type.IsSubclassOf(nodeWindowBaseType) && !type.ContainsGenericParameters)
                {
                    var method = type.GetMethod("OnOpenAssetsFun",BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy);
                    if (method != null)
                    {
                        var result = method.Invoke(null, new object[] { id });
                        if ((bool)result) return true;
                    }
                }
            }
            return false;
        }
        
        /// <summary>
        /// 节点视图数据更新
        /// </summary>
        private void NodeView_OnDataUpdate()
        {
            m_nodeTitle.style.backgroundColor = PortColor.HexToColor("#B04600");
        }

        private void SaveButton_Clicked()
        {
            NodeTreeData.NodeTreeData = m_nodeView.NodeTreeDataBase;
            m_nodeView.SetIsDataUpdateSave();
            m_nodeTitle.style.backgroundColor = PortColor.HexToColor("#006198");
            Debug.Log("保存");
        }

        private void NodeView_OnViewScale(Vector2 arg0)
        {
            UpdatePosHint();
        }

        private void NodeView_OnMouseMove(Vector2 arg0)
        {
            UpdatePosHint();
        }
        private void OnKeyDownEvent(KeyDownEvent evt)
        {
            // 检查是否按下了Ctrl + S
            if (evt.ctrlKey && evt.keyCode == KeyCode.S)
            {
                SaveButton_Clicked();
                evt.StopPropagation(); // 阻止事件继续传播
            }
        }
        private void UpdatePosHint()
        {
            m_posHint.text = $"GPos X:{m_nodeView.GraphLocalMousePosition.x.ToString("f0")} Y:{m_nodeView.GraphLocalMousePosition.y.ToString("f0")}       " +
                $"Pos X:{m_nodeView.GraphMousePosition.x.ToString("f0")} Y:{m_nodeView.GraphMousePosition.y.ToString("f0")}        " +
                $"Scale:{m_nodeView.ViewScale.x.ToString("f1")}";
        }
    }

    /// <summary>
    /// 处理实例化窗口逻辑
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <typeparam name="T2"></typeparam>
    public abstract class NodeWindowBase<T,T2> : NodeWindowBase 
        where T : NodeWindowBase<T,T2> 
        where T2 : NodeTreeFile
    {
        
        public static T CreateWindow()
        {
            T window = CreateWindow<T>(typeof(T));
            window.minSize = new Vector2(800, 600);
            window.Show();
            return window;
        }
        /// <summary>
        /// 双击NodeTree资源是触发
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public static bool OnOpenAssetsFun(int id)
        {
            var arg = EditorUtility.InstanceIDToObject(id);
            if (arg is not T2 tree) return false;
            
            // 如果是两个系统的树,关闭老的打开新的
            int instanceID = tree.GetInstanceID();
            if (m_windows.ContainsKey(instanceID))
            {
                m_windows[instanceID].Close();
                m_windows.Remove(instanceID);
            }

            NodeWindowBase<T,T2> nodeWindowBase = CreateWindow();
            nodeWindowBase.NodeTreeData = tree;
            nodeWindowBase.NodeTreeData.ResetData();
            nodeWindowBase.Init();
            m_windows.Add(instanceID,nodeWindowBase);
                
            return true;
        }
    }
}